package cc.htdf.gwc.radar.utils;

import cc.htdf.gwc.radar.exception.nc.OpenNcException;
import cc.htdf.gwc.radar.exception.nc.ReadNcException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ucar.ma2.Array;
import ucar.ma2.InvalidRangeException;
import ucar.nc2.Attribute;
import ucar.nc2.NetcdfFile;
import ucar.nc2.Variable;

import java.io.IOException;
import java.util.LinkedList;
import java.util.List;

/**
 * Created by JT on 2017/8/5.
 */
public class RadarNcFileUtils {

    private RadarNcFileUtils() {}

    private static Logger logger = LoggerFactory.getLogger(RadarNcFileUtils.class);

    public static final String CODE_ERROR = "500";

    /**
     * 打开NC文件
     * @param filepath：文件路径
     * @return
     * @throws Exception
     */
    public static NetcdfFile openNc(String filepath) {
        NetcdfFile nc = null;
        try {
            nc = NetcdfFile.open(filepath);
        } catch (IOException e) {
            String message = String.format("打开NC文件失败：%s,文件不完整或文件格式错误！", filepath);
            throw new OpenNcException(CODE_ERROR, message);
        }
        return nc;
    }

    /**
     * 关闭NC文件
     * @param nc
     */
    public static void closeNc(NetcdfFile nc) {
        try {
            nc.close();
        } catch (IOException e) {
            logger.warn("nc 文件[{}]已关闭，无需重复关闭！", nc.getLocation());
        }
    }

    /**
     * 读取NC文件变量
     * @param nc
     * @param variableName
     * @return
     * @throws Exception
     */
    public static Long readVariableLong(NetcdfFile nc, String variableName)  {
        Variable variable = nc.findVariable(variableName);
        String message = String.format("文件[%s]中未找到变量[%s]，或变量类型[%s]错误", nc.getLocation(), variableName, Double.class);
        try {
            if (variable == null) throw new ReadNcException(CODE_ERROR, message);
            Double variableDouble = variable.readScalarDouble();
            return variableDouble.longValue();
        } catch (IOException e) {
            throw new ReadNcException(CODE_ERROR, message);
        }
    }

    /**
     * 读取NC文件变量列表
     * @param nc：NC文件句柄
     * @param variableName：变量名称
     * @return
     * @throws Exception
     */
    public static List<Long> readVariableList(NetcdfFile nc, String variableName) {
        Variable variable = nc.findVariable(variableName);
        String message = String.format("文件[%s]中未找到变量[%s]，或变量类型[%s]错误", nc.getLocation(), variableName, Array.class);
        try {
            if (variable == null) throw new ReadNcException(CODE_ERROR, message);
            Array data = variable.read();
            LinkedList list = new LinkedList();
            while (data.hasNext()) {
                list.add(Double.valueOf(data.nextDouble()).longValue());
            }
            return list;
        } catch (IOException e) {
            throw new ReadNcException(CODE_ERROR, message);
        }
    }

    /**
     * 读取NC文件属性
     * @param nc：文件句柄
     * @param attributeName：属性名称
     * @return
     * @throws Exception
     */
    public static Double readAttributeDouble(NetcdfFile nc, String attributeName) {
        Attribute attribute = nc.findGlobalAttribute(attributeName);
        String message = String.format("文件[%s]中未找到属性[%s]", nc.getLocation(), attributeName);
        if (attribute == null) throw new ReadNcException(CODE_ERROR, message);
        return attribute.getValues().getDouble(0);
    }


    /**
     * 读取NC文件 数据维度
     * @param nc：文件句柄
     * @param dimensionName：维度名称
     * @return
     */
    public static Integer readDimensionInteger(NetcdfFile nc, String dimensionName) {
        return nc.findDimension(dimensionName).getLength();

    }


    public static float[][][] readDatasThreeDimension(NetcdfFile nc, String name)  {
        Variable variable = nc.findVariable(name);

        try {
            String message = String.format("文件[%s]中未找到数据[%s]", nc.getLocation(), name);
            if (variable == null) throw new ReadNcException(CODE_ERROR, message);
            Array array = variable.read(new int[]{0, 0, 0}, variable.getShape()).reduce();
            float[][][] arr = (float[][][]) array.copyToNDJavaArray();
            return arr;
        } catch (IOException e) {
            String message = String.format("文件[%s]读取数据失败！Exception:%s", nc.getLocation(), e.getMessage());
            throw new ReadNcException(CODE_ERROR, message);
        } catch (InvalidRangeException e) {
            String message = String.format("文件[%s]中，数据格式不匹配[%s]，Exception：%s", nc.getLocation(), Array.class, e.getMessage());
            throw new ReadNcException(CODE_ERROR, message);
        }
    }
}
